/*
 * Copyright (c) 2020 Fraunhofer FOKUS and others. All rights reserved.
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contact: mosaic@fokus.fraunhofer.de
 */

package org.eclipse.mosaic.fed.mqtt.protocol;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;

/**
 * Obu protocol
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ObuProtocol extends AbstractProtocol{

    private ObuHeader header;

    private ObuBody body;

    public ObuProtocol() {

    }

    public ObuProtocol(ObuHeader header, ObuBody body) {
        this.header = header;
        this.body = body;
    }

    public ObuHeader getHeader() {
        return header;
    }

    public ObuBody getBody() {
        return body;
    }

    @Override
    @JsonIgnore
    public String getId() {
        return body.getVehicleId();
    }


    @JsonIgnoreProperties
    public static class ObuHeader {

    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public static class ObuBody {

        private String vehicleId;

        private Integer messageId;

        private Long timestampGNSS;

        private Double velocityGNSS;

        private Position position;

        private Double heading;

        private Integer tapPos;

        private Long steeringAngle;

        private Double velocityCAN;

        private Double accelerationLon;

        private Double accelerationLat;

        private Double accelerationVer;

        private Long yawRate;

        private Long accelPos;

        private Long engineSpeed;

        private Long engineTorque;

        private Integer brakeFlag;

        private Long brakePos;

        private Long brakePressure;

        private Long fuelConsumption;

        private String driveMode;

        private Position destLocation;


        public ObuBody() {

        }

        public ObuBody(String vehicleId, Integer messageId, Long timestampGNSS, Double velocityGNSS, Position position,
                       Double heading, Integer tapPos, Long steeringAngle, Double velocityCAN, Double accelerationLon,
                       Double accelerationLat, Double accelerationVer, Long yawRate, Long accelPos, Long engineSpeed,
                       Long engineTorque, Integer brakeFlag, Long brakePos, Long brakePressure, Long fuelConsumption,
                       String driveMode, Position destLocation) {
            this.vehicleId = vehicleId;
            this.messageId = messageId;
            this.timestampGNSS = timestampGNSS;
            this.velocityGNSS = velocityGNSS;
            this.position = position;
            this.heading = heading;
            this.tapPos = tapPos;
            this.steeringAngle = steeringAngle;
            this.velocityCAN = velocityCAN;
            this.accelerationLon = accelerationLon;
            this.accelerationLat = accelerationLat;
            this.accelerationVer = accelerationVer;
            this.yawRate = yawRate;
            this.accelPos = accelPos;
            this.engineSpeed = engineSpeed;
            this.engineTorque = engineTorque;
            this.brakeFlag = brakeFlag;
            this.brakePos = brakePos;
            this.brakePressure = brakePressure;
            this.fuelConsumption = fuelConsumption;
            this.driveMode = driveMode;
            this.destLocation = destLocation;
        }

        public String getVehicleId() {
            return vehicleId;
        }

        public Integer getMessageId() {
            return messageId;
        }

        public Long getTimestampGNSS() {
            return timestampGNSS;
        }

        public Double getVelocityGNSS() {
            return velocityGNSS;
        }

        public Position getPosition() {
            return position;
        }

        public Double getHeading() {
            return heading;
        }

        public Integer getTapPos() {
            return tapPos;
        }

        public Long getSteeringAngle() {
            return steeringAngle;
        }

        public Double getVelocityCAN() {
            return velocityCAN;
        }

        public Double getAccelerationLon() {
            return accelerationLon;
        }

        public Double getAccelerationLat() {
            return accelerationLat;
        }

        public Double getAccelerationVer() {
            return accelerationVer;
        }

        public Long getYawRate() {
            return yawRate;
        }

        public Long getAccelPos() {
            return accelPos;
        }

        public Long getEngineSpeed() {
            return engineSpeed;
        }

        public Long getEngineTorque() {
            return engineTorque;
        }

        public Integer getBrakeFlag() {
            return brakeFlag;
        }

        public Long getBrakePos() {
            return brakePos;
        }

        public Long getBrakePressure() {
            return brakePressure;
        }

        public Long getFuelConsumption() {
            return fuelConsumption;
        }

        public String getDriveMode() {
            return driveMode;
        }

        public Position getDestLocation() {
            return destLocation;
        }

        public void setVehicleId(String vehicleId) {
            this.vehicleId = vehicleId;
        }

        public void setMessageId(Integer messageId) {
            this.messageId = messageId;
        }

        public void setTimestampGNSS(Long timestampGNSS) {
            this.timestampGNSS = timestampGNSS;
        }

        public void setVelocityGNSS(Double velocityGNSS) {
            this.velocityGNSS = velocityGNSS;
        }

        public void setPosition(Position position) {
            this.position = position;
        }

        public void setHeading(Double heading) {
            this.heading = heading;
        }

        public void setTapPos(Integer tapPos) {
            this.tapPos = tapPos;
        }

        public void setSteeringAngle(Long steeringAngle) {
            this.steeringAngle = steeringAngle;
        }

        public void setVelocityCAN(Double velocityCAN) {
            this.velocityCAN = velocityCAN;
        }

        public void setAccelerationLon(Double accelerationLon) {
            this.accelerationLon = accelerationLon;
        }

        public void setAccelerationLat(Double accelerationLat) {
            this.accelerationLat = accelerationLat;
        }

        public void setAccelerationVer(Double accelerationVer) {
            this.accelerationVer = accelerationVer;
        }

        public void setYawRate(Long yawRate) {
            this.yawRate = yawRate;
        }

        public void setAccelPos(Long accelPos) {
            this.accelPos = accelPos;
        }

        public void setEngineSpeed(Long engineSpeed) {
            this.engineSpeed = engineSpeed;
        }

        public void setEngineTorque(Long engineTorque) {
            this.engineTorque = engineTorque;
        }

        public void setBrakeFlag(Integer brakeFlag) {
            this.brakeFlag = brakeFlag;
        }

        public void setBrakePos(Long brakePos) {
            this.brakePos = brakePos;
        }

        public void setBrakePressure(Long brakePressure) {
            this.brakePressure = brakePressure;
        }

        public void setFuelConsumption(Long fuelConsumption) {
            this.fuelConsumption = fuelConsumption;
        }

        public void setDriveMode(String driveMode) {
            this.driveMode = driveMode;
        }

        public void setDestLocation(Position destLocation) {
            this.destLocation = destLocation;
        }

        public static class Builder {
            private String vehicleId;

            private int messageId;

            private long timestampGNSS;

            private double velocityGNSS;

            private Position position;

            private double heading;

            private int tapPos;

            private long steeringAngle;

            private double velocityCAN;

            private double accelerationLon;

            private double accelerationLat;

            private double accelerationVer;

            private long yawRate;

            private long accelPos;

            private long engineSpeed;

            private long engineTorque;

            private int brakeFlag;

            private long brakePos;

            private long brakePressure;

            private long fuelConsumption;

            private String driveMode;

            private Position destLocation;

            public Builder setVehicleId(String vehicleId) {
                this.vehicleId = vehicleId;
                return this;
            }

            public Builder setTimestampGNSS(long timestampGNSS) {
                this.timestampGNSS = timestampGNSS;
                return this;
            }

            public Builder setPosition(Position position) {
                this.position = position;
                return this;
            }

            public Builder setHeading(double heading) {
                this.heading = heading;
                return this;
            }

            public Builder setVelocityCAN(double velocityCAN) {
                this.velocityCAN = velocityCAN;
                return this;
            }

            public Builder setAccelerationLon(double accelerationLon) {
                this.accelerationLon = accelerationLon;
                return this;
            }

            public Builder defaultValue() {
                this.messageId = 9239;
                this.velocityGNSS = 0.0;
                this.tapPos = 2;
                this.steeringAngle = 10200000;
                this.accelerationLat = 156.0;
                this.accelerationVer = 145.0;
                this.yawRate = 11200;
                this.accelPos = 20;
                this.engineSpeed = 12;
                this.engineTorque = 5600;
                this.brakeFlag = 1;
                this.brakePos = 200;
                this.brakePressure = 38992;
                this.fuelConsumption = 39892;
                this.driveMode = "1";
                this.destLocation = new Position(0.0, 0.0, null);
                return this;
            }

            public ObuBody build() {
                return new ObuBody(vehicleId, messageId, timestampGNSS, velocityGNSS, position, heading, tapPos,
                        steeringAngle, velocityCAN, accelerationLon, accelerationLat, accelerationVer, yawRate, accelPos,
                        engineSpeed, engineTorque, brakeFlag, brakePos, brakePressure, fuelConsumption, driveMode, destLocation);
            }
        }
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public static class Position {
        private Double latitude;

        private Double longitude;

        private Double elevation;


        public Position() {
        }

        public Position(Double latitude, Double longitude, Double elevation) {
            this.latitude = latitude;
            this.longitude = longitude;
            this.elevation = elevation;
        }

        public Double getLatitude() {
            return latitude;
        }

        public Double getLongitude() {
            return longitude;
        }

        public Double getElevation() {
            return elevation;
        }

        public void setLatitude(Double latitude) {
            this.latitude = latitude;
        }

        public void setLongitude(Double longitude) {
            this.longitude = longitude;
        }

        public void setElevation(Double elevation) {
            this.elevation = elevation;
        }
    }


}
